#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：pid_control_example 
@File ：deviation_correction2.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/5/14 下午11:28 
"""

import json
import time
from socket import socket
from typing import Any, Dict

# 导入简单PID库
from simple_pid import PID


# 创建一个参数配置类
class Parameters:
	def __init__(self, parameters_file: str):
		self.parameters = self.load_parameters(parameters_file)

	def load_parameters(self, parameters_file: str) -> Dict[str, Dict[str, Any]]:
		with open(parameters_file, 'r') as file:
			return json.load(file)

	def get_parameters(self, board_type: str) -> Dict[str, Any]:
		# 如果板坯类型存在于参数文件中，则返回对应的参数配置；否则返回默认参数配置
		return self.parameters.get(board_type, self.parameters["default"])


# 定义获取数据的函数，模拟通过 socket 获取数据
def get_data_from_socket(host: str, port: int) -> Dict[str, float]:
	# 模拟通过 socket 获取数据的过程
	# 在实际情况下，你需要实现真实的数据获取逻辑
	# 这里返回一个字典，包含实际值和板坯类型
	data = {
		"actual_value": 0.5,  # 模拟实际值
		"board_type": "type1"  # 模拟板坯类型
	}
	return data


# 主程序
def main(parameters_file: str):
	# 创建参数配置对象
	parameters = Parameters(parameters_file)

	# 创建 socket 监听端口
	with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
		s.bind((config.host, config.port))
		s.listen()
		print(f"Listening on {config.host}:{config.port}...")
		conn, addr = s.accept()
		with conn:
			print(f"Connected by {addr}")
			while True:
				# 获取数据
				data = get_data_from_socket(config.host, config.port)
				actual_value = data["actual_value"]
				board_type = data["board_type"]

				# 获取板坯类型对应的参数配置
				params = parameters.get_parameters(board_type)

				# 创建 PID 控制器对象并使用参数配置初始化
				pid = PID(params["kp"], params["ki"], params["kd"], setpoint=params["setpoint"])

				# 计算 PID 控制器的输出
				correction = pid(actual_value)

				# 在实际应用中，可以将 correction 发送给控制系统进行纠偏操作
				# 这里只是简单地打印出来
				print(f"Correction: {correction}")

				# 模拟间隔 200ms
				time.sleep(0.2)


if __name__ == "__main__":
	# 参数文件路径
	PARAMETERS_FILE = "parameters.json"

	# 执行主程序
	main(PARAMETERS_FILE)
